package com.fau.fm.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Hibernate;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.fau.fm.entity.MedicalAdmin;
import com.fau.fm.entity.MedicalGroup;
import com.fau.fm.entity.MedicalKeyValue;
import com.fau.fm.entity.MedicalPlatform;
import com.fau.fm.entity.MedicalResource;
import com.fau.fm.entity.MedicalRole;
import com.fau.fm.entity.MedicalStaffBasic;
import com.fau.fm.service.IUserManagerService;
import com.fau.fm.util.Page;
import com.fau.fm.util.ParamUtil;
import com.fau.fm.util.SystemConfig;
import com.fau.fm.util.ValidatorUtil;

/**
 * @desc 用户管理Service实现类
 */
@Service
@Transactional(readOnly = true)
public class UserManagerService extends BaseService implements IUserManagerService {
	@Resource
	private Md5PasswordEncoder encoder;
	protected final MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

	@SuppressWarnings("deprecation")
	@Override
	public MedicalAdmin findUserByName(String username) {
		MedicalAdmin admin = (MedicalAdmin) iBaseDao.getObjectByHql("from MedicalAdmin a where a.username = ?", username);
		if (ObjectUtils.equals(null, admin)) 
			throw new UsernameNotFoundException(messages.getMessage("JdbcDaoImpl.notFound", new Object[]{username}, "Username {0} not found"), username);
			Hibernate.initialize(admin.getRoleSet());
		if(0 == admin.getRoleSet().size())
			throw new UsernameNotFoundException(messages.getMessage("JdbcDaoImpl.noAuthority", new Object[] {username}, "User {0} has no GrantedAuthority"), username);
		return admin;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<MedicalResource> findAllResource() {
		List<MedicalResource> list = iBaseDao.getBySql("from MedicalResource a where a.typeName = ?", null, SystemConfig.FM_SYSTEM_TYPE);
		for(MedicalResource mr : list) {
			Hibernate.initialize(mr.getRoleSet());
		}
		return list;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<MedicalResource> findRootResource() {
		List<MedicalResource> list = this.iBaseDao.getBySql("from MedicalResource a where a.isMenus=? ", null, SystemConfig.ROOT_RESOURCE_TYPE);
		for(MedicalResource mr : list) {
			Hibernate.initialize(mr.getRoleSet());
		}
		return list;
	}
	
	public List<MedicalResource> loadMenu() {
		MedicalAdmin user = (MedicalAdmin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		List<MedicalResource> list = new ArrayList<MedicalResource>();
		for(MedicalRole mr : user.getRoleSet()) {
			MedicalRole role = (MedicalRole) iBaseDao.getObject(MedicalRole.class, mr.getId());
			for(MedicalResource resource : role.getResourceSet()) {
				if(SystemConfig.IS_MENUS == resource.getIsMenus() && SystemConfig.FM_SYSTEM_TYPE.equals(resource.getTypeName())){
					list.add(resource);
				}
			}
		}
		for(int i = 0; i < list.size(); i++) {
			for(int j = list.size() - 1; j > i; j--) {
				if(list.get(i).getId().equals(list.get(j).getId())){
					list.remove(j);
				}
			}
		}
		return list;
	}

	@Override
	public Page findStaffBasicByPage(Map<String, Object> map, String eid, String name) {
		StringBuilder statusSql = new StringBuilder("from MedicalStaffBasic m where m.user.enterpriseId = ? ");
		StringBuilder countSql = new StringBuilder("select count(*) from MedicalStaffBasic m where m.user.enterpriseId = ? ");
		List<Object> objectList = new ArrayList<Object>();
		objectList.add(eid);
		if(StringUtils.isNotBlank(name)) {
			name = name.trim().replaceAll("_", "chr(95)").replaceAll("%", "chr(37)");
			statusSql.append(" and m.user.name like ? ");
			countSql.append(" and m.user.name like ? ");
			objectList.add("%"+name+"%");
		}
		statusSql.append(" order by m.createTime desc ");
		Page page = this.iBaseDao.getPage(ParamUtil.getInteger(map,"pageIndex",1),ParamUtil.getInteger(map, "pageSize", 20), map, countSql.toString(), statusSql.toString(), objectList);
		List<MedicalStaffBasic> list = new ArrayList<MedicalStaffBasic>();
		for(Object obj : page.getResult()) {
			MedicalStaffBasic basic = (MedicalStaffBasic) obj;
			MedicalKeyValue keyVal = (MedicalKeyValue) this.iBaseDao.getValueByKey("0", SystemConfig.HM_SYSTEM_TYPE, basic.getUser().getDeptType());
			basic.setDept(keyVal.getKeyValue());
			Hibernate.initialize(basic.getUser().getGroup());
			list.add(basic);
		}
		return page;
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean insertStaffBasicSalary(MedicalStaffBasic staffSalary) {
		MedicalAdmin admin = (MedicalAdmin) this.iBaseDao.getObject(MedicalAdmin.class, staffSalary.getUid());
		staffSalary.setUser(admin);
		Set<ConstraintViolation<Object>> errorInfo = ValidatorUtil.validateObj(staffSalary);
		if(errorInfo.size() > 0) {
			return false;
		} else {
			return this.iBaseDao.saveObject(staffSalary);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<MedicalAdmin> findSpecificStaff(String dept, String position) {
		List<MedicalAdmin> list = this.iBaseDao.getBySql("from MedicalAdmin a where a.deptType=? and a.isLeader=? ", null, dept,position);
		return list;
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void deleteStaffBasic(String ids) {
		String[] temp = ids.split("-");
		for (String s : temp) {
			this.iBaseDao.updateHql("delete from MedicalStaffBasic a where a.id=? ", s);
		}
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean updateStaffBasicSalary(MedicalStaffBasic staffSalary) {
		MedicalStaffBasic medicalStaffBasic2 = (MedicalStaffBasic) this.iBaseDao.getObject(MedicalStaffBasic.class, staffSalary.getId());
		medicalStaffBasic2.setBasic(staffSalary.getBasic());
		medicalStaffBasic2.setUpdateTime(new Date());
		Set<ConstraintViolation<Object>> errorInfo = ValidatorUtil.validateObj(medicalStaffBasic2);
		if(errorInfo.size() > 0) {
			return false;
		} else {
			return this.iBaseDao.saveObject(medicalStaffBasic2);
		}
	}

	@Override
	public boolean includeUserBasicSalary(String uid) {
		MedicalStaffBasic basic = (MedicalStaffBasic) this.iBaseDao.getObjectByHql("from MedicalStaffBasic m where m.user.id = ? ", uid);
		if(null == basic) {
			return true;
		} else {
			return false;
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<MedicalPlatform> findByEidAll(String eid, String type) {
		return this.iBaseDao.getBySql("from MedicalPlatform m where m.eid = ? and m.platformType = ? ", null, eid, type);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<MedicalGroup> findByPlatformIdAll(String platformId) {
		return this.iBaseDao.getBySql("from MedicalGroup m where m.platform.id = ? ", null, platformId);
	}
	
	

}